/*
 * Copyright 2022-2027 中国信息通信研究院云计算与大数据研究所
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */ 
package com.service.impl;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.web.client.RestTemplate;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.common.calculation.TimeUtil;
import com.common.constant.AccountConstant;
import com.common.constant.ChkuplogConstant;
import com.common.constant.ClusterConstant;
import com.common.constant.ParamConstant;
import com.common.constant.ProcessConstant;
import com.common.constant.TrancfgConstant;
import com.common.constant.UniformityConstant;
import com.common.context.SpringContextUtils;
import com.common.fastjson.JsonResult;
import com.common.util.CommUtil;
import com.localMapper.ClustercfgMapper;
import com.localMapper.LocalTranLogMapper;
import com.localMapper.ParamcfgMapper;
import com.localMapper.ProcessListMapper;
import com.mapper.InitialData;
import com.mapper.ReadDataConfig;
import com.mapper.ReadTranConfig;
import com.mapper.Salary;
import com.mapper.UniformityMapper;
import com.pojo.ChkuplogCount;
import com.pojo.Clustercfg;
import com.pojo.DataConfig;
import com.pojo.Paramcfg;
import com.pojo.ProcessList;
import com.pojo.SalaryBranchCount;
import com.pojo.Trancfg;
import com.pojo.TranlogCount;
import com.service.MasterNodeService;

@Service
@Scope("prototype")
public class MasterNodeServiceImpl extends Thread implements MasterNodeService{

    @Autowired
    private UniformityMapper uniformityMapper;
    @Autowired
    private LocalTranLogMapper localTranLogMapper;
    
    @Autowired
    DataSourceTransactionManager dataSourceTransactionManager;
    @Autowired
    TransactionDefinition transactionDefinition;
    
    private final Logger logger = LoggerFactory.getLogger(MasterNodeServiceImpl.class);

    private StringBuffer buf = new StringBuffer();
    @Autowired
    private ReadTranConfig readTranConfig;
    @Autowired
    private ReadDataConfig readDataCfg;
    @Autowired
    private ClustercfgMapper clustercfgMapper;
    @Autowired
    private ProcessListMapper processListMapper;
    @Autowired
    private ParamcfgMapper paramcfgMapper;
    @Autowired
    private Salary salary;
    private String datacfg_id = "";
    private String trancfg_testid = "";
    private String process_id = "";
    private String isolationLevel = "";
    @Autowired
	private RestTemplate restTemplate;
    @Autowired
    private InitialData initialData;
	@Override
	public void run() {
		long now = System.currentTimeMillis();
        DataConfig df = readDataCfg.readDataCfg(datacfg_id);
        if(df == null) {
    		buf.append("数据规模参数配置错误");
    		insertProcessList(100,buf.toString());
        	return;
        }
       	Integer branchCount = initialData.countBranch();
    	if(branchCount==null||branchCount<1) {
            buf.append("尚未进行数据初始化，请先进行数据初始化。");
            insertProcessList(100,buf.toString());
    		return;
    	}
        boolean isCanRun = false;
        List<Clustercfg> clusterList = clustercfgMapper.getClustercfg();
        Map<String,Clustercfg> slaveMap = new HashMap<String,Clustercfg>();
        for(Clustercfg clustercfg:clusterList) {
        	if(ClusterConstant.CLUSTER_SLAVE.equals(clustercfg.getCluster_type())) {
        		if(ClusterConstant.SLAVE_SUCCESS.equals(clustercfg.getCluster_stat())) {
        			if(ClusterConstant.SLAVE_STOP.equals(clustercfg.getCluster_finish())) {
        				isCanRun = true;//有子节点可以运行
        				slaveMap.put(clustercfg.getCluster_id(), clustercfg);
        			}
        		}
        	}
        }
        if(!isCanRun) {
        	buf.append("目前正在运行业务数据,请过会再试");
    		insertProcessList(100,buf.toString());
        	return;
        }
		DataCleanServiceImpl dataCleanServiceImpl = SpringContextUtils.getBean(DataCleanServiceImpl.class);//进行业务数据清理
		dataCleanServiceImpl.run();
		buf.append("开始运行业务测试");
		buf.append("<br/>");
    	//插入进度表
		insertProcessList(1,buf.toString());
		Paramcfg paramcfg = paramcfgMapper.getParamByName(ParamConstant.PARAM_START_UNIFORMITY);
		BigDecimal afterAccountBale =BigDecimal.ZERO;
		System.out.println("开始执行一致性测试："+CommUtil.getNowTime());
        if(UniformityConstant.UNIFORMITY_START_UNIFORMITY.equals(paramcfg.getParam_value())) {
        	afterAccountBale = uniformityMapper.sumAccount();
        }
        uniformityCheck(afterAccountBale);//测试前一致性
		System.out.println("结束执行一致性测试："+CommUtil.getNowTime());
        Map<String,Clustercfg> slaveAvailableMap = new HashMap<String,Clustercfg>();
        for(String clustercfg:slaveMap.keySet()) {
        	try {
        	 	//发送开始进行业务运行
        		JSONObject json = new JSONObject();
        		json.put("datacfg_id", datacfg_id);
        		json.put("trancfg_testid", trancfg_testid);
        		json.put("process_id", process_id);
        		json.put("cluster_id", clustercfg);
        		HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
                HttpEntity<JSONObject> entity = new HttpEntity<JSONObject>(JSON.parseObject(json.toJSONString()), headers);
            	logger.info(" MasterNodeServiceImpl send slave {} ",json.toJSONString());
                HttpEntity<String> resultObj = restTemplate.exchange(slaveMap.get(clustercfg).getCluster_url()+"begin", HttpMethod.POST, entity, String.class);
        		JsonResult jsonResult = JSON.parseObject(resultObj.getBody(), JsonResult.class);
        		if(jsonResult.getCode()==0) {
        			slaveAvailableMap.put(clustercfg, slaveMap.get(clustercfg));
        		}
            	logger.info(" MasterNodeServiceImpl result slave {} ",jsonResult.toString());
			} catch (Exception e) {
            	logger.error(" MasterNodeServiceImpl send slave is error {} ",e);
			}
        }
        if(slaveAvailableMap.size()<1) {
        	buf.append("目前正在运行业务数据,请过会再试");
    		insertProcessList(100,buf.toString());
        	return;
        }
		System.out.println("开始执行业务测试："+CommUtil.getNowTime());
        printDataConfigure(df);//拼装数据配置输出
		AtomicityServiceImpl atomicityCommit = SpringContextUtils.getBean(AtomicityServiceImpl.class);
		AtomicityServiceImpl atomicityUnCommit = SpringContextUtils.getBean(AtomicityServiceImpl.class);
    	startAtomicityCheck(atomicityCommit,atomicityUnCommit,df);//开始原子性检测
    	IsolationMainServiceImpl isolationMain = SpringContextUtils.getBean(IsolationMainServiceImpl.class);
    	startIsolationCheck(isolationMain,df);//开始隔离性检测
		Map<String,Integer> threadConfigure = new HashMap<String,Integer>();
	    List<SalaryBranchCount> branchCountList = salary.countBranchSalary();
		printRunConfigure(threadConfigure,branchCountList,slaveAvailableMap);//拼装运行配置输出
		insertProcessList(5,buf.toString());
		long time = 0;
		long countTime = System.currentTimeMillis();
		int result = 0;
		long businessTime = System.currentTimeMillis();
		while(true) {
            try {
				Thread.sleep(5000);
				time+=5;
				boolean isFinish = true;
				List<Clustercfg> clusterStatus = clustercfgMapper.getClustercfg();
            	for(Clustercfg clustercfg : clusterStatus) {
            		if(slaveAvailableMap.containsKey(clustercfg.getCluster_id())) {
            			if(!ClusterConstant.SLAVE_STOP.equals(clustercfg.getCluster_finish())) {
            				isFinish = false;
            			}
            		}
            	}
            	if(isFinish) {
            		System.out.println("业务总耗时:"+(System.currentTimeMillis()-businessTime));
            		break;
            	}
            	if(time%10==0) {
            		long timeStr = System.currentTimeMillis();
            		int process = setRunProcess(threadConfigure,branchCountList,slaveAvailableMap);//获取运行结果
            		System.out.println("当前交易数量:"+(process-result)/((timeStr-countTime)/1000));
            		int total = threadConfigure.get("transferRunNum")+threadConfigure.get("queryRunNum")+threadConfigure.get("depositRunNum")+threadConfigure.get("withdrawRunNum")+threadConfigure.get("salaryRunNum");
            		System.out.println("当前交易进度:"+process+"/"+total*slaveAvailableMap.size());
            		countTime = System.currentTimeMillis();
            		result = process;
            	}
			} catch (InterruptedException e) {
				e.printStackTrace();
            	logger.error(" MasterNodeServiceImpl while true is error {} ",e);
				return;
			}
        }
		System.out.println("结束执行业务测试："+CommUtil.getNowTime());
		stopAtomicityCheck(atomicityCommit,atomicityUnCommit);//停止原子性检测
		stopIsolationCheck(isolationMain);//停止隔离性检测
		System.out.println("开始执行一致性测试："+CommUtil.getNowTime());
        uniformityCheck(afterAccountBale);//测试后检测一致性
		System.out.println("结束执行一致性测试："+CommUtil.getNowTime());
        durabilityCheck();//持久性检测
        //拼装输出结果
        printThreadOut(buf,System.currentTimeMillis()-now,threadConfigure,branchCountList,slaveAvailableMap.size());
        //插入进度表
		insertProcessList(100,buf.toString());
		//logger.error(buf.toString());
		System.out.println(buf.toString().replaceAll("<br/>", "\n").replaceAll("<font color=\"#409EFF\">", "").replaceAll("</font>", ""));
	}

	private int setRunProcess(Map<String, Integer> threadConfigure, List<SalaryBranchCount> branchCountList, Map<String, Clustercfg> slaveAvailableMap) {
		StringBuffer bufResult = new StringBuffer();
		List<TranlogCount> costList = localTranLogMapper.tranlogCostTimeCount(process_id);
		Map<String,TranlogCount> costMap = new HashMap<String,TranlogCount>();
		for(TranlogCount tranlogCount:costList) {
			costMap.put(tranlogCount.getTrancfg_type(), tranlogCount);
		}
		bufResult.append("<br/>");
		bufResult.append("<font color=\"#409EFF\">业务测试进度：</font>");
		bufResult.append("<br/>");
		int nowRunNum = 0;
		if(costMap.containsKey(TrancfgConstant.TRANCFG_ACCOUNTS_TRANSFER)) {
			TranlogCount tc = costMap.get(TrancfgConstant.TRANCFG_ACCOUNTS_TRANSFER);
			bufResult.append(threadConfigure.get("transferProcNum")*slaveAvailableMap.size()).append("线程并发转账交易共").append(threadConfigure.get("transferRunNum")*slaveAvailableMap.size()+"笔，当前已执行").append(tc.getNum()).append("笔");
			nowRunNum+=tc.getNum();
		}else {
			bufResult.append(threadConfigure.get("transferProcNum")*slaveAvailableMap.size()).append("线程并发转账交易当前已执行").append(0).append("笔");
		}
		bufResult.append("<br/>");
		if(costMap.containsKey(TrancfgConstant.TRANCFG_ACCOUNTS_QUERY)) {
			TranlogCount tc = costMap.get(TrancfgConstant.TRANCFG_ACCOUNTS_QUERY);
			bufResult.append(threadConfigure.get("queryProcNum")*slaveAvailableMap.size()).append("线程并发账户查询共").append(threadConfigure.get("queryRunNum")*slaveAvailableMap.size()+"笔，当前已执行").append(tc.getNum()).append("笔");
			nowRunNum+=tc.getNum();
		}else {
			bufResult.append(threadConfigure.get("queryProcNum")*slaveAvailableMap.size()).append("线程并发账户查询当前已执行").append(0).append("笔");
		}
		bufResult.append("<br/>");
		if(costMap.containsKey(TrancfgConstant.TRANCFG_ACCOUNTS_DEPOSIT)) {
			TranlogCount tc = costMap.get(TrancfgConstant.TRANCFG_ACCOUNTS_DEPOSIT);
			bufResult.append(threadConfigure.get("depositProcNum")*slaveAvailableMap.size()).append("线程并发账户存款共").append(threadConfigure.get("depositRunNum")*slaveAvailableMap.size()+"笔，当前已执行").append(tc.getNum()).append("笔");
			nowRunNum+=tc.getNum();
		}else {
			bufResult.append(threadConfigure.get("depositProcNum")*slaveAvailableMap.size()).append("线程并发账户存款当前已执行").append(0).append("笔");
		}
		bufResult.append("<br/>");
		if(costMap.containsKey(TrancfgConstant.TRANCFG_ACCOUNTS_WITHDRAW)) {
			TranlogCount tc = costMap.get(TrancfgConstant.TRANCFG_ACCOUNTS_WITHDRAW);
			bufResult.append(threadConfigure.get("withdrawProcNum")*slaveAvailableMap.size()).append("线程并发账户取款共").append(threadConfigure.get("withdrawRunNum")*slaveAvailableMap.size()+"笔，当前已执行").append(tc.getNum()).append("笔");
			nowRunNum+=tc.getNum();
		}else {
			bufResult.append(threadConfigure.get("withdrawProcNum")*slaveAvailableMap.size()).append("线程并发账户取款当前已执行").append(0).append("笔");
		}
		bufResult.append("<br/>");
		if(costMap.containsKey(TrancfgConstant.TRANCFG_ACCOUNTS_SALARY)) {
			TranlogCount tc = costMap.get(TrancfgConstant.TRANCFG_ACCOUNTS_SALARY);
			bufResult.append(threadConfigure.get("salaryProcNum")*slaveAvailableMap.size()).append("线程并发代发工资共").append((threadConfigure.get("salaryRunNum")*slaveAvailableMap.size())/2+"笔，当前已执行").append(tc.getNum()/2).append("笔").append("(").append(branchCountList.size())
				.append("个代发网点，重复代发").append(threadConfigure.get("salaryRepeatNum")).append("次，共").append(tc.getNum()/2).append("笔)");
			nowRunNum+=tc.getNum();
		}else {
			bufResult.append(threadConfigure.get("salaryProcNum")*slaveAvailableMap.size()).append("线程并发代发工资当前已执行").append(0).append("笔");
		}
		int total = threadConfigure.get("transferRunNum")+threadConfigure.get("queryRunNum")+threadConfigure.get("depositRunNum")+threadConfigure.get("withdrawRunNum")+threadConfigure.get("salaryRunNum");
		int processInt = ((int) (((float)nowRunNum / (float)(total*slaveAvailableMap.size())) * 100))-5;
		if(processInt>5) {
			insertProcessList(processInt,buf.toString()+ bufResult.toString());
		}else {
			insertProcessList(6,buf.toString()+ bufResult.toString());
		}
		return nowRunNum;

	}

	private void insertProcessList(int process_perc,String buf) {
		ProcessList processList = new ProcessList();
		processList.setDatacfg_id(datacfg_id);
		processList.setProcess_id(process_id);
		processList.setTrancfg_id(trancfg_testid);
		processList.setProcess_type(ProcessConstant.PROCESS_BUSINESS);
		processList.setProcess_content(buf);
		processList.setProcess_time(new Timestamp(System.currentTimeMillis()));
		processList.setProcess_perc(process_perc);
		processListMapper.insertProcessList(processList);
	}

	private void durabilityCheck() {
		DurabilityServiceImpl durabilityServiceImpl = SpringContextUtils.getBean(DurabilityServiceImpl.class);
		durabilityServiceImpl.run();
	}

	/**
	 * 停止隔离性检测
	 * @param isolationMain
	 */
	private void stopIsolationCheck(IsolationMainServiceImpl isolationMain) {
		isolationMain.setStop(true);
		try {
			Thread.sleep(5000);
		} catch (InterruptedException e) {
			logger.error("MasterNodeServiceImpl run stopIsolationCheck e {} ",e);
		}		
	}

	/**
	 * 开始隔离性检测
	 * @param isolationMain
	 * @param df
	 */
	private void startIsolationCheck(IsolationMainServiceImpl isolationMain, DataConfig df) {
		isolationMain.setDatacfg_accnum(df.getDatacfg_accnum());
		isolationMain.setIsolationLevel(isolationLevel);
		isolationMain.start();		
	}


	/**
	 * 停止原子性检测
	 * @param atomicityCommit
	 * @param atomicityUnCommit
	 */
	private void stopAtomicityCheck(AtomicityServiceImpl atomicityCommit, AtomicityServiceImpl atomicityUnCommit) {
		atomicityCommit.setStop(true);
		atomicityUnCommit.setStop(true);
		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			logger.error("MasterNodeServiceImpl run stopAtomicityCheck e {} ",e);
		}
	}

	/**
	 * 开启原子性检测
	 * @param atomicityCommit
	 * @param atomicityUnCommit
	 * @param df 
	 */
	private void startAtomicityCheck(AtomicityServiceImpl atomicityCommit, AtomicityServiceImpl atomicityUnCommit, DataConfig df) {
		atomicityCommit.setType("1");
		atomicityCommit.setPrex("80");
		atomicityCommit.setDatacfg_accnum(df.getDatacfg_accnum());
		atomicityCommit.start();
		atomicityUnCommit.setType("2");
		atomicityUnCommit.setPrex("81");
		atomicityUnCommit.setDatacfg_accnum(df.getDatacfg_accnum());
		atomicityUnCommit.start();
	}


	private void uniformityCheck(BigDecimal afterAccountBale) {
		if(afterAccountBale==null) {
			afterAccountBale = BigDecimal.ZERO;
		}
		//开启一致性线程
		UniformityServiceImpl uniformityService = SpringContextUtils.getBean(UniformityServiceImpl.class);
		uniformityService.setAfterAccountBale(afterAccountBale);
		uniformityService.setProcess_id(process_id);
		uniformityService.run();
        logger.info(" MasterNodeServiceImpl run thread UniformityServiceImpl start ");		
	}

	private void printRunConfigure(Map<String, Integer> threadConfigure, List<SalaryBranchCount> branchCountList, Map<String, Clustercfg> slaveAvailableMap) {
		 	Trancfg param = new Trancfg();
	        param.setTrancfg_testid(trancfg_testid);
	      	List<Trancfg> tfList = readTranConfig.readTranConfig(param);
	      	threadConfigure.put("transferRunNum", 0);
	      	threadConfigure.put("transferProcNum", 0);
	      	threadConfigure.put("salaryRunNum", 0);
	      	threadConfigure.put("salaryProcNum", 0);
	      	threadConfigure.put("queryRunNum", 0);
	      	threadConfigure.put("queryProcNum", 0);
	      	threadConfigure.put("salaryRepeatNum", 0);
	      	threadConfigure.put("depositRunNum", 0);
		    threadConfigure.put("depositProcNum", 0);
			threadConfigure.put("withdrawRunNum",0);
	      	threadConfigure.put("withdrawProcNum",0);
			//代发工资线程数初始化
	      	if(tfList!=null&&tfList.size()>0) {
	    		buf.append("运行配置：").append("运行节点数量").append(slaveAvailableMap.size());
	      		for(Trancfg tf:tfList) {
	      			buf.append("<br/>");
	      			if(tf.getTrancfg_id().equals(TrancfgConstant.TRANCFG_ACCOUNTS_TRANSFER)) {
	      				buf.append("转账交易：").append(tf.getTrancfg_runnum()).append("笔").append("，");
	      				buf.append("转账线程：").append(tf.getTrancfg_procnum()).append("；");
	      		      	threadConfigure.put("transferRunNum", tf.getTrancfg_runnum());
	      		      	threadConfigure.put("transferProcNum", tf.getTrancfg_procnum());
	      			}else if(tf.getTrancfg_id().equals(TrancfgConstant.TRANCFG_ACCOUNTS_SALARY)) {
	      				if(branchCountList.size()!=0) {
	      			      	threadConfigure.put("salaryRunNum", branchCountList.size());
		      			    threadConfigure.put("salaryProcNum",tf.getTrancfg_procnum());
	      				}
	      			    threadConfigure.put("salaryRepeatNum",tf.getTrancfg_runnum());
	      				int salaryTotal = 0;
	      				for(SalaryBranchCount salaryBranchCount : branchCountList) {
	      					salaryTotal+=salaryBranchCount.getNum();
	      				}
	      				buf.append("代发工资：").append(salaryTotal).append("条(").append(branchCountList.size())
	      				.append("个代发网点，重复代发").append(tf.getTrancfg_runnum()).append("次，共").append((salaryTotal*tf.getTrancfg_runnum())/2).append("笔)").append("，");
      			      	threadConfigure.put("salaryRunNum", branchCountList.size()*tf.getTrancfg_runnum());
	      				buf.append("代发线程：").append(threadConfigure.get("salaryProcNum")).append("；");
	      			    threadConfigure.put("salaryTotalNum",salaryTotal*tf.getTrancfg_runnum());
	      			}else if(tf.getTrancfg_id().equals(TrancfgConstant.TRANCFG_ACCOUNTS_QUERY)) {
	      				buf.append("账户查询：").append(tf.getTrancfg_runnum()).append("笔").append("，");
	      				buf.append("查询线程：").append(tf.getTrancfg_procnum()).append("；");
	      				threadConfigure.put("queryRunNum", tf.getTrancfg_runnum());
	      		      	threadConfigure.put("queryProcNum", tf.getTrancfg_procnum());
	      			}else if(tf.getTrancfg_id().equals(TrancfgConstant.TRANCFG_ACCOUNTS_DEPOSIT)) {
	      				buf.append("账户存款：").append(tf.getTrancfg_runnum()).append("笔").append("，");
	      				buf.append("存款线程：").append(tf.getTrancfg_procnum()).append("；");
	       				threadConfigure.put("depositRunNum", tf.getTrancfg_runnum());
	      		      	threadConfigure.put("depositProcNum", tf.getTrancfg_procnum());
	      			}else if(tf.getTrancfg_id().equals(TrancfgConstant.TRANCFG_ACCOUNTS_WITHDRAW)) {
	      				buf.append("账户取款：").append(tf.getTrancfg_runnum()).append("笔").append("，");
	      				buf.append("取款线程：").append(tf.getTrancfg_procnum()).append("；");
	       				threadConfigure.put("withdrawRunNum", tf.getTrancfg_runnum());
	      		      	threadConfigure.put("withdrawProcNum", tf.getTrancfg_procnum());
	      			}else if(tf.getTrancfg_id().equals(TrancfgConstant.TRANCFG_ACCOUNTS_INVENTORY)) {
	      				buf.append("资产盘点：").append(tf.getTrancfg_runnum()).append("笔").append("，");
	      				buf.append("盘点线程：").append(tf.getTrancfg_procnum()).append("；");
	      				threadConfigure.put("inventoryRunNum", tf.getTrancfg_runnum());
	      		      	threadConfigure.put("inventoryProcNum", tf.getTrancfg_procnum());
	      			}
	      		}
	      	}		
	}


	/**
	 * 拼装数据格式输出
	 * @param df
	 */
	private void printDataConfigure(DataConfig df) {
		buf.append("<font color=\"#409EFF\">数据配置：");
		buf.append("网点数").append(df.getDatacfg_brhnum()).append("，");
		buf.append("科目数").append(df.getDatacfg_sjnonum()).append("，");
		buf.append("客户数").append(df.getDatacfg_cusnum()).append("，");
		buf.append("账户数").append(df.getDatacfg_accnum()).append("</font>");
		buf.append("<br/>");		
	}


	/**
	 * 拼装输出返回
	 * @param buf
	 * @param costTotal
	 * @param threadConfigure
	 * @param branchCountList 
	 * @param i 
	 */
	private void printThreadOut(StringBuffer buf, long costTotal, Map<String, Integer> threadConfigure, List<SalaryBranchCount> branchCountList, int nodeNum) {
		List<TranlogCount> costList = localTranLogMapper.tranlogCostTimeCount(process_id);
		Map<String,TranlogCount> costMap = new HashMap<String,TranlogCount>();
		for(TranlogCount tranlogCount:costList) {
			costMap.put(tranlogCount.getTrancfg_type(), tranlogCount);
		}
		buf.append("<br/>");
		buf.append("<font color=\"#409EFF\">业务测试明细：</font>");
		buf.append("<br/>");
		buf.append("测试总耗时：").append(TimeUtil.formatDuration(costTotal));
		buf.append("<br/>");
		if(costMap.containsKey(TrancfgConstant.TRANCFG_ACCOUNTS_TRANSFER)) {
			TranlogCount tc = costMap.get(TrancfgConstant.TRANCFG_ACCOUNTS_TRANSFER);
			buf.append(threadConfigure.get("transferProcNum")*nodeNum).append("线程并发转账交易").append(tc.getNum()).append("笔，");
			buf.append("总耗时").append(TimeUtil.formatDuration((tc.getTotal_cost().longValue()/threadConfigure.get("transferProcNum"))/nodeNum)).append("，");
			buf.append("平均耗时").append(TimeUtil.formatDuration(tc.getAvg_cost().longValue())).append("，");
			buf.append("最大耗时").append(TimeUtil.formatDuration(tc.getMax_cost().longValue())).append("，");
			long cost = (tc.getTotal_cost().longValue()/threadConfigure.get("transferProcNum"))/nodeNum/1000;
			if(cost==0) {
				buf.append("TPS每秒 ").append((tc.getNum()));
			}else {
				buf.append("TPS每秒 ").append((tc.getNum())/cost);
			}

		}else {
			buf.append(threadConfigure.get("transferProcNum")*nodeNum).append("线程并发转账交易").append(0).append("笔，");
			buf.append("总耗时").append(0).append("，");
			buf.append("平均耗时").append(0).append("，");
			buf.append("最大耗时").append(0).append("，");
			buf.append("TPS每秒 ").append(0);
		}
		buf.append("<br/>");
		if(costMap.containsKey(TrancfgConstant.TRANCFG_ACCOUNTS_QUERY)) {
			TranlogCount tc = costMap.get(TrancfgConstant.TRANCFG_ACCOUNTS_QUERY);
			buf.append(threadConfigure.get("queryProcNum")*nodeNum).append("线程并发账户查询").append(tc.getNum()).append("笔，");
			buf.append("总耗时").append(TimeUtil.formatDuration((tc.getTotal_cost().longValue()/threadConfigure.get("queryProcNum"))/nodeNum)).append("，");
			buf.append("平均耗时").append(TimeUtil.formatDuration(tc.getAvg_cost().longValue())).append("，");
			buf.append("最大耗时").append(TimeUtil.formatDuration(tc.getMax_cost().longValue())).append("，");
			long cost = (tc.getTotal_cost().longValue()/threadConfigure.get("queryProcNum"))/nodeNum/1000;
			if(cost==0) {
				buf.append("TPS每秒 ").append((tc.getNum()));
			}else {
				buf.append("TPS每秒 ").append((tc.getNum())/cost);
			}
		}else {
			buf.append(threadConfigure.get("queryProcNum")*nodeNum).append("线程并发账户查询").append(0).append("笔，");
			buf.append("总耗时").append(0).append("，");
			buf.append("平均耗时").append(0).append("，");
			buf.append("最大耗时").append(0).append("，");
			buf.append("TPS每秒 ").append(0);

		}
		buf.append("<br/>");
		if(costMap.containsKey(TrancfgConstant.TRANCFG_ACCOUNTS_DEPOSIT)) {
			TranlogCount tc = costMap.get(TrancfgConstant.TRANCFG_ACCOUNTS_DEPOSIT);
			buf.append(threadConfigure.get("depositProcNum")*nodeNum).append("线程并发账户存款").append(tc.getNum()).append("笔，");
			buf.append("总耗时").append(TimeUtil.formatDuration((tc.getTotal_cost().longValue()/threadConfigure.get("depositProcNum"))/nodeNum)).append("，");
			buf.append("平均耗时").append(TimeUtil.formatDuration(tc.getAvg_cost().longValue())).append("，");
			buf.append("最大耗时").append(TimeUtil.formatDuration(tc.getMax_cost().longValue())).append("，");
			long cost = (tc.getTotal_cost().longValue()/threadConfigure.get("depositProcNum"))/nodeNum/1000;
			if(cost==0) {
				buf.append("TPS每秒 ").append((tc.getNum()));
			}else {
				buf.append("TPS每秒 ").append((tc.getNum())/cost);
			}
		}else {
			buf.append(threadConfigure.get("depositProcNum")*nodeNum).append("线程并发账户存款").append(0).append("笔，");
			buf.append("总耗时").append(0).append("，");
			buf.append("平均耗时").append(0).append("，");
			buf.append("最大耗时").append(0).append("，");
			buf.append("TPS每秒 ").append(0);
		}
		buf.append("<br/>");
		if(costMap.containsKey(TrancfgConstant.TRANCFG_ACCOUNTS_WITHDRAW)) {
			TranlogCount tc = costMap.get(TrancfgConstant.TRANCFG_ACCOUNTS_WITHDRAW);
			buf.append(threadConfigure.get("withdrawProcNum")*nodeNum).append("线程并发账户取款").append(tc.getNum()).append("笔，");
			buf.append("总耗时").append(TimeUtil.formatDuration((tc.getTotal_cost().longValue()/threadConfigure.get("withdrawProcNum"))/nodeNum)).append("，");
			buf.append("平均耗时").append(TimeUtil.formatDuration(tc.getAvg_cost().longValue())).append("，");
			buf.append("最大耗时").append(TimeUtil.formatDuration(tc.getMax_cost().longValue())).append("，");
			long cost = (tc.getTotal_cost().longValue()/threadConfigure.get("withdrawProcNum"))/nodeNum/1000;
			if(cost==0) {
				buf.append("TPS每秒 ").append((tc.getNum()));
			}else {
				buf.append("TPS每秒 ").append((tc.getNum())/cost);
			}
		}else {
			buf.append(threadConfigure.get("withdrawProcNum")*nodeNum).append("线程并发账户取款").append(0).append("笔，");
			buf.append("总耗时").append(0).append("，");
			buf.append("平均耗时").append(0).append("，");
			buf.append("最大耗时").append(0).append("，");
			buf.append("TPS每秒 ").append(0);

		}
		buf.append("<br/>");
		if(costMap.containsKey(TrancfgConstant.TRANCFG_ACCOUNTS_SALARY)) {
			TranlogCount tc = costMap.get(TrancfgConstant.TRANCFG_ACCOUNTS_SALARY);
			buf.append(threadConfigure.get("salaryProcNum")*nodeNum).append("线程并发代发工资").append((threadConfigure.get("salaryTotalNum")*nodeNum)/2).append("笔").append("(").append(branchCountList.size())
				.append("个代发网点，重复代发").append(threadConfigure.get("salaryRepeatNum")).append("次，共").append((threadConfigure.get("salaryTotalNum")*nodeNum)/2).append("笔)").append("，");
			buf.append("总耗时").append(TimeUtil.formatDuration((tc.getTotal_cost().longValue()/threadConfigure.get("salaryProcNum"))/nodeNum)).append("，");
			buf.append("平均耗时").append(TimeUtil.formatDuration(tc.getAvg_cost().longValue())).append("，");
			buf.append("最大耗时").append(TimeUtil.formatDuration(tc.getMax_cost().longValue()));
		}else {
			buf.append(threadConfigure.get("salaryProcNum")*nodeNum).append("线程并发代发工资").append(0).append("笔，");
			buf.append("总耗时").append(0).append("，");
			buf.append("平均耗时").append(0).append("，");
			buf.append("最大耗时").append(0);
		}
		buf.append("<br/>");
		System.out.println("开始执行资产盘点："+CommUtil.getNowTime());
		if(threadConfigure.get("inventoryRunNum")!=null&&threadConfigure.get("inventoryRunNum")>0) {
			long cost = System.currentTimeMillis();
			List<String> customerList = uniformityMapper.accountInventory();
			if(customerList!=null&&customerList.size()>0) {
				logger.info(" MasterNodeServiceImpl printThreadOut accountInventory failure customerList {} ",customerList);
				buf.append("资产盘点失败，总耗时").append(TimeUtil.formatDuration(System.currentTimeMillis()-cost));
			}else {
				logger.info(" MasterNodeServiceImpl printThreadOut accountInventory success ");
				buf.append("资产盘点成功，总耗时").append(TimeUtil.formatDuration(System.currentTimeMillis()-cost));
			}
		}else {
			logger.info(" MasterNodeServiceImpl printThreadOut accountInventory zero ");
			buf.append("资产盘点0笔");
		}
		System.out.println("结束执行资产盘点："+CommUtil.getNowTime());
		buf.append("<br/>");
		buf.append("<font color=\"#409EFF\">ACID测试明细：</font>");
		buf.append("<br/>");
		List<ChkuplogCount> chkuplogCountList = uniformityMapper.chkuplogCount();
		Map<String,ChkuplogCount> chkuplogCountMap = new HashMap<String,ChkuplogCount>();
		for(ChkuplogCount chkuplogCount : chkuplogCountList) {
			chkuplogCountMap.put(chkuplogCount.getChkuplog_type().trim()+chkuplogCount.getChkuplog_success().trim(), chkuplogCount);
		}
		int uniformitySuccess = 0;
		int uniformityFailure = 0;
		int atomicitySuccess = 0;
		int atomicityFailure = 0;
		int isolationSuccess = 0;
		int isolationFailure = 0; 
		int durabilitySuccess = 0;
		int durabilityFailure = 0; 
		if(chkuplogCountMap.containsKey(ChkuplogConstant.CHKUPLOG_TYPE_C+AccountConstant.ACCOUNT_TRAN_SUCCESS)) {
			ChkuplogCount cc = chkuplogCountMap.get(ChkuplogConstant.CHKUPLOG_TYPE_C+AccountConstant.ACCOUNT_TRAN_SUCCESS);
			uniformitySuccess = cc.getNum();
		}
		if(chkuplogCountMap.containsKey(ChkuplogConstant.CHKUPLOG_TYPE_C+AccountConstant.ACCOUNT_TRAN_FAILURE)) {
			ChkuplogCount cc = chkuplogCountMap.get(ChkuplogConstant.CHKUPLOG_TYPE_C+AccountConstant.ACCOUNT_TRAN_FAILURE);
			uniformityFailure = cc.getNum();
		}
		if(chkuplogCountMap.containsKey(ChkuplogConstant.CHKUPLOG_TYPE_A+AccountConstant.ACCOUNT_TRAN_SUCCESS)) {
			ChkuplogCount cc = chkuplogCountMap.get(ChkuplogConstant.CHKUPLOG_TYPE_A+AccountConstant.ACCOUNT_TRAN_SUCCESS);
			atomicitySuccess = cc.getNum();
		}
		if(chkuplogCountMap.containsKey(ChkuplogConstant.CHKUPLOG_TYPE_A+AccountConstant.ACCOUNT_TRAN_FAILURE)) {
			ChkuplogCount cc = chkuplogCountMap.get(ChkuplogConstant.CHKUPLOG_TYPE_A+AccountConstant.ACCOUNT_TRAN_FAILURE);
			atomicityFailure = cc.getNum();
		}
		if(chkuplogCountMap.containsKey(ChkuplogConstant.CHKUPLOG_TYPE_I+AccountConstant.ACCOUNT_TRAN_SUCCESS)) {
			ChkuplogCount cc = chkuplogCountMap.get(ChkuplogConstant.CHKUPLOG_TYPE_I+AccountConstant.ACCOUNT_TRAN_SUCCESS);
			isolationSuccess = cc.getNum();
		}
		if(chkuplogCountMap.containsKey(ChkuplogConstant.CHKUPLOG_TYPE_I+AccountConstant.ACCOUNT_TRAN_FAILURE)) {
			ChkuplogCount cc = chkuplogCountMap.get(ChkuplogConstant.CHKUPLOG_TYPE_I+AccountConstant.ACCOUNT_TRAN_FAILURE);
			isolationFailure = cc.getNum();
		}
		if(chkuplogCountMap.containsKey(ChkuplogConstant.CHKUPLOG_TYPE_D+AccountConstant.ACCOUNT_TRAN_SUCCESS)) {
			ChkuplogCount cc = chkuplogCountMap.get(ChkuplogConstant.CHKUPLOG_TYPE_D+AccountConstant.ACCOUNT_TRAN_SUCCESS);
			durabilitySuccess = cc.getNum();
		}
		if(chkuplogCountMap.containsKey(ChkuplogConstant.CHKUPLOG_TYPE_D+AccountConstant.ACCOUNT_TRAN_FAILURE)) {
			ChkuplogCount cc = chkuplogCountMap.get(ChkuplogConstant.CHKUPLOG_TYPE_D+AccountConstant.ACCOUNT_TRAN_FAILURE);
			durabilityFailure = cc.getNum();
		}
		buf.append("一致性测试").append(uniformitySuccess+uniformityFailure).append("笔，");
		buf.append("成功").append(uniformitySuccess).append("笔，");
		buf.append("失败").append(uniformityFailure).append("笔；");
		buf.append("<br/>");
		buf.append("原子性测试").append(atomicitySuccess+atomicityFailure).append("笔，");
		buf.append("成功").append(atomicitySuccess).append("笔，");
		buf.append("失败").append(atomicityFailure).append("笔；");
		buf.append("<br/>");
		buf.append("隔离性测试").append(isolationSuccess+isolationFailure).append("笔，");
		buf.append("成功").append(isolationSuccess).append("笔，");
		buf.append("失败").append(isolationFailure).append("笔；");
		buf.append("<br/>");
		buf.append("持久性测试").append(durabilitySuccess+durabilityFailure).append("笔，");
		buf.append("成功").append(durabilitySuccess).append("笔，");
		buf.append("失败").append(durabilityFailure).append("笔；");
		buf.append("<br/>");
	}
	public String getDatacfg_id() {
		return datacfg_id;
	}


	public void setDatacfg_id(String datacfg_id) {
		this.datacfg_id = datacfg_id;
	}


	public String getTrancfg_testid() {
		return trancfg_testid;
	}

	public void setTrancfg_testid(String trancfg_testid) {
		this.trancfg_testid = trancfg_testid;
	}

	public String getIsolationLevel() {
		return isolationLevel;
	}

	public void setIsolationLevel(String isolationLevel) {
		this.isolationLevel = isolationLevel;
	}

	public String getProcess_id() {
		return process_id;
	}

	public void setProcess_id(String process_id) {
		this.process_id = process_id;
	}

    
    
}